var XForms = {
  elements:[],
  binds:{},
  instances:[],
  append:function(e){
    this.elements.push(e);
    return this;
  },
  xpath:function(node, xpath){
    var doc = node.ownerDocument == null ? node : node.ownerDocument;
    var res = [];
    if(typeof(doc.evaluate)=="function"){
      var xPathRes = doc.evaluate(xpath,node, function(){}, 0, null);
      switch(xPathRes.resultType){
      case xPathRes.BOOLEAN_TYPE:
        res = xPathRes.booleanValue;
        break;
      case xPathRes.NUMBER_TYPE:
        res = xPathRes.numberValue;
        break;
      case xPathRes.STRING_TYPE:
        res = xPathRes.stringValue;
        break;
      default:
        var actualSpan = xPathRes.iterateNext();
        while (actualSpan) {
          res.push(actualSpan);
          actualSpan = xPathRes.iterateNext();
        }
      }
    } else {
      res = node.selectNodes(xpath);
    }
    return res;
  },
  addKeyValidation:function($element, validateKeyCodes) {
    $element.keydown(function (e) {
      return XF_Validate.validateKeyCode(e.keyCode, validateKeyCodes);
    });
  }
}
var xforms_messages={
  "missing_value":"Missing or incorrect value"
}
function XForms_DataType(params){
  var binding = this.getBinding();
  var control = this;
  this.validationMessage=function(msg){
    var done=false;
    this.$element.parents().each(function(){
      if(!done) {
        var $m=$(this).find(".xforms_validationmessage");
        if($m.length==1) {
          $m.html(msg);
        }
      }
    });
  }
  if(binding && this.$element){
    switch(binding.get("type")){
      case 'xforms:string':
        this.$element.bind('change',function(){
          control.validationMessage("");
        });
        break;
      case 'xforms:decimal':
        this.$element.bind('change',function(){
          if(this.value!="" && this.value!=this.value*1){
            control.validationMessage(xforms_messages.missing_value);
          } else {
            control.validationMessage("");
          }
        });
        break;
      case 'xforms:integer':
        this.$element.bind('change',function(){
          if(this.value!="" && this.value!=parseInt(this.value*1)){
            control.validationMessage(xforms_messages.missing_value);
          } else {
            control.validationMessage("");
          }
        });
        break;
      case 'xforms:email':
        this.$element.bind('change',function(){
          if(this.value!="" && !this.value.match(/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i)){
            control.validationMessage(xforms_messages.missing_value);
          } else {
            control.validationMessage("");
          }
        });
        break;
      case 'xforms:dateTime':
        this.$element.attr("readonly", "readonly");
        this.$element.datetimepicker();
        break;
      case 'xforms:date':
        this.$element.attr("readonly", "readonly");
        this.$element.datepicker();
        break;
      case 'xforms:time':
        this.$element.attr("readonly", "readonly");
        this.$element.timepicker();
        break;
      case 'xforms:boolean':
        this.$element.attr("type", "checkbox");
        this.$element.val("true");
        break;
      default:
        this.$element.bind('change',function(){
          control.validationMessage("");
        });
        break;
    }
  }
}
function XForms_Core(params){
  fromServer=false;
  this.params=params;
  this.dependents=[];
  this.dependentsEvents=[];
  if(params.id) this.$element = $('#' + params.id);
  else if(params._xpath) this.$element = $(document.getElementById(params._xpath));
  this.evalAttribute=function(attribute){
    if(typeof this.get(attribute)=="undefined") return;
    var res;
    var data = XForms.instances[0].childNodes[0].toXml();
    if(fromServer){
      $.ajax({
        url:"",
        data:{da:data,si:0,xp:params._xpath,fn:"evalAttribute",pa:JSON.stringify([attribute])},
        method:"get",
        dataType:"json",
        async:false,
        success:function(response){
          res=response;
        },
        failure:function(response){
          throw new Exception(response);
        }
      });
    } else {
      //TODO: Si no tiene params._binding no recupera el contexto.
      var binding = this.getBinding();
      if(binding && binding._parent) {
        //console.log(binding.params._instance.childNodes[0].params._xpath);
        //console.log(this.getBinding()._parent.params._xpath);
        var rootpath = binding._parent.params._xpath.substr(binding.params._instance.childNodes[0].params._xpath.length+1);
        if(rootpath=="")rootpath=".";
        //console.log(rootpath);
        //console.log($(binding.params._instance.childNodes[0].toXml())[0]);
        var ctx=XForms.xpath($(binding.params._instance.childNodes[0].toXml())[0],rootpath);
        //console.log(ctx);
        //console.log(XForms.xpath(ctx[0],'section-2'));
        res = XForms.xpath(ctx[0],this.get(attribute));
        //console.log(res);
      }
    }
    return res;
  };
  this.getUID=function(){
    if(params.id) return params.id;
    else return params._xpath;
  }
  this.getBinding=function(){
    if(params._binding) return XForms.binds[params._binding];
    else return null;
  }
  this.get=function(name){
    return params[name];
  }
  this.bind=function(bind){
    if(bind.validateKeyCodes) {
      XForms.addKeyValidation(this.$element, bind.validateKeyCodes);
    }
  }
  this.getValue=function(){
    var $binding = this.getBinding();
    if($binding) {
      return $binding.getValue();
    } else {
      if(typeof(params.value)!=="undefined") {
        console.log(this.get("value"), this.evalAttribute("value"));
        return this.evalAttribute("value");
        return params.value;
      } else if(this.$element.length==1) {
        return this.$element.val();
      }
    }
  }
  this.setValue=function(value){
    var $binding = this.getBinding();
    if($binding) {
      $binding.setValue(value);
    } else {
      params.value = value;
    }
    if(this.$element.length==1) {
      this.$element.val(value);
    }
    //this.raiseEvent(["xforms-value-changed"]);
    this.raiseEvents();
  }
  this.raiseEvents=function(){
    for(var i=0,l=this.dependents.length;i<l;i++) {
      for(j=0,k=this.dependentsEvents[i].length;j<k;j++){
        var eventName = this.dependentsEvents[i][j];
        var fEventName = eventName.replace("xforms-","on-");
        //console.log(this.dependents[i],"this.dependents[i]."+fEventName.replace(/-(.)/g,function($0,$1){return $1.toUpperCase();})+"()");
        eval("this.dependents[i]."+fEventName.replace(/-(.)/g,function($0,$1){return $1.toUpperCase();})+"()");
      }
    }
  }
  this.bubleEvent=function(eventName){
    for(var i=0,l=this.dependents.length;i<l;i++) {
      var fEventName = eventName.replace("xforms-","on-");
      //console.log(this.dependents[i],"this.dependents[i]."+fEventName.replace(/-(.)/g,function($0,$1){return $1.toUpperCase();})+"()");
      eval("this.dependents[i]."+fEventName.replace(/-(.)/g,function($0,$1){return $1.toUpperCase();})+"()");
    }
  }
  this.appendDependent=function(xform,events){
    if(typeof events == "undefined") throw new Exception("Parameter events is undefined.");
    var i=this.dependents.indexOf(xform);
    if(i==-1) {
      this.dependents.push(xform);
      this.dependentsEvents.push(events);
    } else {
      this.dependentsEvents[i]=this.dependentsEvents[i].concat(events);
    }
  }
  this.onValueChanged=function(){
    this.onRefresh();
  }
  this.onRefresh=function(){
  }
  this.onRefreshRelevant=function(){
    //console.log(this);
    this.bubleEvent("xforms-refresh-relevant");
  }
  if(this.getBinding()) {
    this.getBinding().appendDependent(this, ["xforms-value-changed"]);
  }
  XForms_DataType.call(this, params);
}

$(function(){
  $( document ).tooltip();
  $(".radio").buttonset();
  $("button").button();
  $( ".orbeonPanel" ).accordion({
    heightStyleType:"fill"
  });
  //$( "[xforms_type=xforms\\:date]" ).datepicker();
});
